<script setup lang="ts">
import type { TreeKey } from 'element-plus/lib/components/tree/src/tree.type.js';

import type {
  AppPosition,
  CommonTreeProps,
  FolderProps,
  LayoutSize,
  VersionProps,
} from '@/types';

import {
  type ComponentInternalInstance,
  defineAsyncComponent,
  getCurrentInstance,
  hydrateOnVisible,
  onBeforeUnmount,
  onMounted,
  type PropType,
  reactive,
  ref,
  useTemplateRef,
  watch,
} from 'vue';

import {
  type Action,
  dayjs,
  ElButton,
  ElMessage,
  ElMessageBox,
  ElTree,
} from 'element-plus';
import { customAlphabet } from 'nanoid';

import { Horizontal } from '@/components/core/resize-layout';
import { useAppStore } from '@/store';
import { generateVersion, splitChar } from '@/utils';

defineOptions({
  name: 'WorkRelease',
});
const { nowRect } = defineProps({
  nowRect: {
    default: () => ({}),
    type: Object as PropType<AppPosition>,
  },
});
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10);
const Toolbar = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('./components/release/Toolbar.vue'),
});
const CheckboxVersion = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('./components/release/CheckboxVersion.vue'),
});
const SaveTo = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('../_core/common/SaveTo.vue'),
});
const MonacoEditorSetting = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () =>
    import('@/components/core/coding-editor/src/components/MonacoEditorSetting.vue'),
});
const CodeEditor = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('@/components/core/coding-editor/src/CodeEditor.vue'),
});
const CodeDiffEditor = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('@/components/core/coding-editor/src/CodeDiffEditor.vue'),
});
const VersionDialog = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('./components/release/VersionDialog.vue'),
});
const SelectByFileType = defineAsyncComponent({
  hydrate: hydrateOnVisible(),
  loader: () => import('../_core/common/SelectByFileType.vue'),
});

const appStore = useAppStore();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const baseUrl = proxy?.$config.baseUrl;
const moreSettingElRef = useTemplateRef('moreSettingElRef');
const editorElRef = useTemplateRef('editorElRef');
const saveToRef = useTemplateRef('saveToRef');
const documentElRef = useTemplateRef('documentElRef');
const versionDialogElRef = useTemplateRef('versionDialogElRef');
const selectByFileTypeRef = useTemplateRef('selectByFileTypeRef');
const documentHeight = ref(0);
const contentChanged = ref(false);
const showDiff = ref(false);
const editorValue = ref(nanoid());
const defaultValue = nanoid();
const readonly = ref(false);

const originalOption = ref<VersionProps>(); // 对比旧版内容
const modifiedOption = ref<VersionProps>(); // 当前内容

const modifiedContent = ref<string>(''); // 当前内容（修改后）
const _modifiedContent = ref<string>(''); // 当前原始内容（未修改）
const originalContent = ref<string>(''); // 对比文件内容

const prevValue = ref<string>();
const currentValue = ref<string>();
const prevData = ref<CommonTreeProps>();
const currentData = ref<CommonTreeProps>();
const immediate = ref<boolean>(false);
const versionOptions = ref<Array<VersionProps>>([]);

const treeRef = ref<InstanceType<typeof ElTree>>();

const treeData = ref<CommonTreeProps[]>([]);
const defaultProps = {
  disabled: 'disabled',
  id: 'id',
  label: 'name',
  children: 'children',
};

const layoutSize = reactive<LayoutSize>({
  lw: 0,
  mw: 0,
});

const checkedKeys = ref<Array<TreeKey>>([]);
const treeNodeKeys = ref<Array<TreeKey>>([]);
const demoJson = {
  code: 200, data: [
    {
      id: '1', version: 0, name: '版本管理', remark: '备注v1.0.0', level: 1, children: [
        { id: '1-1', version: 1, name: 'v1.0.0', remark: '备注v1.0.0', level: 2 },
        { id: '1-2', version: 2, name: 'v2.0.0', remark: '备注v2.0.0', level: 2 }
      ]
    },
  ]
}
const devMode = ref(true);// 默认开发模式，生产模式可删除
// 加载左侧版本
async function loadTreeData() {
  try {
    const res = demoJson;

    const { code, data } = res;
    if (code === 200 && data) {
      treeData.value = [];
      data.forEach((m: CommonTreeProps) => {
        versionOptions.value.map((v: VersionProps) => {
          const child = m.children?.find(
            (c: CommonTreeProps) => c.id === v.id,
          );
          if (child) {
            Object.assign(child, v);
          }
          return v;
        });
        m.children?.sort((a: VersionProps, b: VersionProps) => {
          return b.version - a.version;
        });
      });
      treeData.value = data;
    }

  } catch (error) {
    console.error(error);
    treeData.value = [];
  }
}
// 全选
const setCheckedKeys = () => {
  const keys = treeData.value?.map((m: CommonTreeProps) => m.key);
  checkedKeys.value = keys as TreeKey[];
  treeRef.value!.setCheckedKeys(checkedKeys.value, false);
};
const unique = (arr: Array<TreeKey>) => {
  return [...new Set(arr)];
};
const getTreeIds = (data: CommonTreeProps) => {
  if (Array.isArray(data.children)) {
    data.children.forEach((item: CommonTreeProps) => {
      if (!item.disabled) {
        treeNodeKeys.value.push(item.key);
        getTreeIds(item);
      }
    });
  }
  unique(treeNodeKeys.value);
};
// 反选
const setReverseChecked = () => {
  const _checkedKeys = treeRef.value!.getCheckedKeys();
  treeData.value?.forEach((m: CommonTreeProps) => {
    getTreeIds(m);
  });
  const keys = treeNodeKeys.value.filter((m) => {
    return !_checkedKeys.includes(m);
  });
  checkedKeys.value = keys;
  treeRef.value!.setCheckedKeys(checkedKeys.value, false);
};
// 清空
const resetChecked = () => {
  checkedKeys.value = [];
  treeRef.value!.setCheckedKeys(checkedKeys.value, false);
};
function mappingTree(
  data: CommonTreeProps[],
  checkedKeys: TreeKey[],
  checkedResult: CommonTreeProps[],
) {
  data.forEach((item: CommonTreeProps) => {
    if (item.children) {
      mappingTree(item.children, checkedKeys, checkedResult);
    }
    if (checkedKeys.includes(item.id)) {
      checkedResult.push(item);
    }
  });
}
// 删除选中的版本
const removeChecked = () => {
  const _checkedKeys = treeRef.value!.getCheckedKeys();
  if (_checkedKeys.length === 0) {
    ElMessage.warning('请选择要删除的版本');
    return;
  }
  ElMessageBox.confirm('确定删除选中的版本？', '提示', {
    buttonSize: 'small',
    cancelButtonText: '取消',
    confirmButtonText: '确定',
    customClass: 'wos-common-confirm',
    type: 'warning',
  })
    .then(() => {
      // TODO: 删除
      const checkedResult: CommonTreeProps[] = [];
      mappingTree(treeData.value, _checkedKeys, checkedResult);
      const paths = checkedResult.map((m) => m.path);
      const ids = new Set(checkedResult.map((m) => m.id));
      if (devMode) {
        ElMessage.success('对接后台API，自定义实现功能');
        return;
      }
      const url = `${baseUrl}/release/delete`;
      const options = versionOptions.value?.filter((m) => !ids.has(m.id));
      const body = {
        mapping: options,
        paths,
      };
      fetch(url, {
        body: JSON.stringify(body),
        headers: {
          'Content-Type': 'application/json;charset=utf-8',
        },
        method: 'DELETE',
      })
        .then((response) => response.json())
        .then((res) => {
          const { code, msg } = res;
          if (code === 200) {
            versionOptions.value = options;
            ElMessage.success(msg || '删除成功');
          } else {
            ElMessage.error(msg || '删除失败');
          }
        });
      loadTreeData();
    })
    .catch(() => { });
};
// 加载当前内容
const loadModifiedContent = (id: string, from: string) => {
  modifiedContent.value = '';
  try {
    if (devMode) {
      modifiedContent.value = `demo最新内容`;
      _modifiedContent.value = `demo最新内容`;
      ElMessage.success('对接后台API，自定义实现功能');
      return;
    }
    const url = `${baseUrl}/release/version/${id}?from=${from}`;
    fetch(url, {
      method: 'GET',
    })
      .then((response) => response.json())
      .then((res) => {
        const { code, data } = res;
        if (code === 200 && data) {
          modifiedContent.value = data;
          _modifiedContent.value = data;
        }
      });
  } catch (error) {
    console.log(error);
    modifiedContent.value = '';
    _modifiedContent.value = '';
  } finally {
    contentChanged.value = false;
  }
};
// 加载对比文件内容
const loadOriginalContent = (id: string, from: string) => {
  originalContent.value = '';
  try {
    if (devMode) {
      originalContent.value = `demo对比内容`;
      showDiff.value = true;
      ElMessage.success('对接后台API，自定义实现功能');
      return;
    }
    const url = `${baseUrl}/release/version/${id}?from=${from}`;
    fetch(url, {
      method: 'GET',
    })
      .then((response) => response.json())
      .then((res) => {
        const { code, data } = res;
        if (code === 200 && data) {
          originalContent.value = data;
          showDiff.value = true;
        }
      });
  } catch (error) {
    console.log(error);
    originalContent.value = '';
    showDiff.value = false;
  }
};

// 确定切换对话框
async function openConfirm() {
  const res = await ElMessageBox.confirm(
    '您还未保存页面内容，确定需要离开吗？',
    '提示',
    {
      buttonSize: 'small',
      cancelButtonText: '取消',
      closeOnClickModal: false,
      confirmButtonText: '确定',
      customClass: 'wos-common-confirm',
      draggable: true,
    },
  )
    .then(() => {
      return 'confirm';
    })
    .catch((error: Action) => {
      return error;
    });
  return res;
}

const handleNodeClick = async (data: CommonTreeProps) => {
  readonly.value = data.readonly;
  if (contentChanged.value && data.id !== currentValue.value) {
    const res = await openConfirm();
    if (res !== 'confirm') {
      treeRef.value?.setCurrentKey(prevValue.value);
      currentValue.value = prevValue.value;
      currentData.value = prevData.value;
      return;
    }
  }
  const { id, parent, type } = data;
  if (type === 2) {
    // 文件夹忽略
    return;
  }
  modifiedOption.value = versionOptions.value.find((item) => item.id === id);
  currentValue.value = id;
  prevValue.value = id;
  currentData.value = data;
  prevData.value = data;
  loadModifiedContent(id, parent);
};

// 比较文件
const onCompare = (e: Event, data?: CommonTreeProps) => {
  e.stopPropagation();
  if (!data || data.id === defaultValue) {
    ElMessage.error('当前版本无法比较');
    return;
  }
  const { id, parent } = data;
  originalOption.value = versionOptions.value.find((m) => m.id === data.id);
  loadOriginalContent(id, parent);
};

// 删除文件
const onDelete = (e: Event, item?: CommonTreeProps) => {
  e.stopPropagation();
  if (!item || item.id === defaultValue) {
    ElMessage.error('当前版本无法删除');
    return;
  }
  ElMessageBox.confirm(
    `删除后将无法恢复，确定删除${item.name}版本吗？`,
    '提示',
    {
      buttonSize: 'small',
      cancelButtonText: '取消',
      closeOnClickModal: false,
      confirmButtonText: '确定',
      customClass: 'wos-common-confirm',
      draggable: true,
    },
  )
    .then(() => {
      try {
        if (devMode) {
          ElMessage.success('对接后台API，自定义实现功能');
          return;
        }
        const url = `${baseUrl}/release/delete/${item.id}?from=${item.parent}`;
        const options = versionOptions.value?.filter((m) => m.id !== item.id);
        const body = {
          mapping: options,
        };
        fetch(url, {
          body: JSON.stringify(body),
          headers: {
            'Content-Type': 'application/json;charset=utf-8',
          },
          method: 'DELETE',
        })
          .then((response) => response.json())
          .then((res) => {
            const { code, msg } = res;
            if (code === 200) {
              ElMessage.success(msg || '删除成功');
            } else {
              ElMessage.error(msg || '删除失败');
            }
          });
      } catch (error) {
        console.log(error);
        currentValue.value = defaultValue;
        prevValue.value = undefined;
        currentData.value = undefined;
        prevData.value = undefined;
      } finally {
        contentChanged.value = false;
        loadTreeData();
      }
    })
    .catch(() => {
      console.log('取消删除');
    });
};

// 保存文件
const onSave = () => {
  try {
    const { id, parent: from } = currentData.value as CommonTreeProps;
    const options = versionOptions.value;
    const body = {
      mapping: options,
      schema: modifiedContent.value,
    };
    if (devMode) {
      ElMessage.success('对接后台API，自定义实现功能');
      return;
    }
    const url = `${baseUrl}/release/save/${id}?immediate=${immediate.value}&from=${from}`;
    fetch(url, {
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
      method: 'POST',
    })
      .then((response) => response.json())
      .then((res) => {
        const { code, msg } = res;
        if (code === 200) {
          ElMessage.success(msg);
          loadTreeData();
        } else {
          ElMessage.error(msg);
        }
      });
  } catch (error) {
    console.log(error);
    ElMessage.error('保存失败，请稍后重试');
  } finally {
    contentChanged.value = false;
  }
};

const onMoveToConfirm = (data: { path: string }) => {
  if (!data.path) {
    ElMessage.error('无效的路径名称');
    return;
  }
  let newVersion = versionOptions.value.find(
    (m) => m.id === currentValue.value,
  );
  const children = treeData.value?.find((m) => m.name === data.path)?.children;
  let version = 0;
  if (children) {
    version = Math.max(
      ...children.map((o: { version: number }) => {
        return o.version || 0;
      }),
    );
  }

  version =
    (Number.isNaN(version) || !Number.isFinite(version) ? 0 : version) + 1;

  const newId = nanoid();
  currentData.value = {
    date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
    id: newVersion?.id || newId,
    parent: data.path,
  };
  if (newVersion) {
    newVersion.version = version;
  } else {
    newVersion = {
      date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      id: newId,
      name: `${generateVersion(version)}`,
      remark: '新建版本',
      version,
    };
    versionOptions.value.unshift(newVersion);
    currentValue.value = newId;
  }
  onSave();
};
// 提交
const onCommit = () => {
  const currentVersion = versionOptions.value.find(
    (m) => m.id === currentValue.value,
  );
  if (!currentVersion) {
    ElMessage.error('当前版本不存在');
    return;
  }
  ElMessageBox.prompt('请输入提交的版本说明', '提交版本', {
    buttonSize: 'small',
    cancelButtonText: '取消',
    confirmButtonText: '确定',
    customClass: 'wos-common-confirm',
    draggable: true,
    inputErrorMessage: '无效的信息，请重新输入',
    inputPlaceholder: '请输入提交的版本说明',
    inputValue: currentVersion.remark,
  })
    .then(({ value }) => {
      const version = (currentVersion.version || 0) + 1;
      const newId = nanoid();
      const newVersion = {
        date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
        id: newId,
        name: `${generateVersion(version)}`,
        remark: value,
        version,
      };
      versionOptions.value.unshift(newVersion);
      currentValue.value = newId;
      if (currentData.value) {
        Object.assign(currentData.value, {
          date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
          id: newId,
        });
        onSave();
      } else {
        versionDialogElRef.value?.open();
      }
    })
    .catch(() => {
      console.log('取消');
    });
};
// 发布
const onRelease = () => {
  if (contentChanged.value) {
    ElMessage.warning('您还未保存页面内容，请先保存文件！');
    return;
  } else if (!currentData.value) {
    ElMessage.warning('请选择需要发布的版本！');
    return;
  }
  const name = currentData.value?.name;
  saveToRef.value?.open({
    checkName: 'release.txt',// 发布文件名，自定义
    exts: [],
    title: `【发布 ${name} 文件】选择具体路径`,
  });
};

// 发布到具体路径
const onReleaseToConfirm = (data: {
  from?: string;
  name?: string;
  path?: string;
}) => {
  const id = currentData.value?.id;
  if (!data || !id) return;
  const from = currentData.value?.parent;
  try {
    const fullPath = `${data.path}${splitChar}${data.name}`;
    ElMessageBox.confirm(
      `如果${fullPath}文件存在，则将被覆盖，是否确定发布？`,
      '发布确定',
      {
        buttonSize: 'small',
        cancelButtonText: '取消',
        closeOnClickModal: false,
        confirmButtonText: '确定',
        customClass: 'wos-common-confirm',
        draggable: true,
      },
    )
      .then(() => {
        if (devMode) {
          ElMessage.success('对接后台API，自定义实现功能');
          return;
        }
        const url = `${baseUrl}/release/release/${id}?from=${from}`;
        const body = {
          target: fullPath,
        };
        fetch(url, {
          body: JSON.stringify(body),
          headers: {
            'Content-Type': 'application/json;charset=utf-8',
          },
          method: 'POST',
        })
          .then((response) => response.json())
          .then((res) => {
            const { code, msg } = res;
            if (code === 200) {
              ElMessage.success(msg || '发布成功');
            } else {
              ElMessage.error(msg || '发布失败，请稍后重试');
            }
          });
      })
      .catch((error: Action) => {
        console.log(error);
      });
  } catch (error) {
    console.log(error);
    ElMessage.error('发布失败，请稍后重试');
  } finally {
    loadTreeData();
  }
};

// 打开文件
const onSelectConfirm = (item: FolderProps) => {
  const { fullPath } = item;
  try {
    const url = `${baseUrl}/file/load?path=${fullPath}`;
    fetch(url, {
      method: 'GET',
    })
      .then((response) => response.text())
      .then((res) => {
        modifiedContent.value = res;
        readonly.value = false;
      });
  } catch (error) {
    console.log(error);
    ElMessage.error('请求发生了错误，请稍后重试');
  }
};

// 检查生产环境版本与本地版本是否存在差异
const onPull = () => {
  try {
        if (devMode) {
          ElMessage.success('对接后台API，自定义实现功能');
          return;
        }
    const url = `${baseUrl}/release/check`;
    fetch(url, {
      method: 'GET',
    })
      .then((response) => response.json())
      .then((res) => {
        const { code, data, msg } = res;
        if (code === 200 && data) {
          const { prodData } = data;
          if (prodData === modifiedContent.value) {
            ElMessage.success('本地最新版本文件与生产环境文件一致');
          } else {
            ElMessageBox.confirm(
              '本地最新版本文件与生产环境文件存在差异，是否查看？',
              '提示',
              {
                buttonSize: 'small',
                cancelButtonText: '取消',
                closeOnClickModal: false,
                confirmButtonText: '查看差异',
                customClass: 'wos-common-confirm',
                draggable: true,
              },
            )
              .then(() => {
                originalContent.value = prodData;
                originalOption.value = {
                  date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
                  id: nanoid(),
                  name: '生产环境文件',
                  remark: '生产环境文件',
                  version: 0,
                };
                showDiff.value = true;
              })
              .catch((error: Action) => {
                console.log(error);
              });
          }
        } else {
          ElMessage.error(msg || '比较文件发生错误，请稍后重试');
        }
      });
  } catch (error) {
    console.log(error);
    ElMessage.error('请求发生了错误，请稍后重试');
  }
};

// 菜单指令
const onCommand = (data: { command: string }) => {
  switch (data.command) {
    case 'commit': {
      onCommit();
      break;
    }
    case 'cover': {
      modifiedContent.value = originalContent.value;
      contentChanged.value = true;
      editorElRef.value?.dispose(editorValue.value);
      break;
    }
    case 'exitCompare': {
      editorElRef.value?.dispose(editorValue.value);
      break;
    }
    case 'newFile': {
      if (contentChanged.value) {
        ElMessage.warning('您还未保存页面内容，请先保存文件！');
        return;
      }
      treeRef.value?.setCurrentKey(undefined); // 清空选中
      _modifiedContent.value = '';
      modifiedContent.value = '';
      originalContent.value = '';
      currentData.value = undefined;
      currentValue.value = undefined;
      prevData.value = undefined;
      prevValue.value = undefined;
      contentChanged.value = true;
      readonly.value = false;
      break;
    }
    case 'openFile': {
      selectByFileTypeRef.value?.open({
        exts: ['.py'],
        title: '选择需要打开的文件',
      });
      break;
    }
    case 'pull': {
      onPull();
      break;
    }
    case 'release': {
      onRelease();
      break;
    }
    case 'saveFile': {
      if (!currentData.value) {
        versionDialogElRef.value?.open();
      } else if (currentValue.value) {
        onSave();
      }
      break;
    }
    case 'setting': {
      // 新文件检查文件夹内相同文件名是否存在
      moreSettingElRef.value?.open();
      break;
    }
    // No default
  }
};
const onEditorDiffDispose = () => {
  originalContent.value = '';
  showDiff.value = false;
};

// 水平分隔左右宽度
const onHorizontalResize = (data: { lw: number; mw: number }) => {
  Object.assign(layoutSize, data);
};
// 新增环境分组
const addEnvironment = () => {
  ElMessageBox.prompt('请输入环境名称', '新建环境', {
    buttonSize: 'small',
    cancelButtonText: '取消',
    confirmButtonText: '确定',
    customClass: 'wos-common-confirm',
    draggable: true,
    inputErrorMessage: '无效的名称，请重新输入',
    inputPattern: /^[a-z0-9]+$/i,
    inputPlaceholder: '请输入新的环境名称',
    inputValue: 'NewEnvironment',
  }).then(({ value }) => {
    if (
      treeData.value &&
      treeData.value.some((item: CommonTreeProps) => item.name === value)
    ) {
      ElMessage.error('环境名称已存在，请重新输入');
      return;
    }
    try {
      const postData = { name: value };
      const url = `${baseUrl}/release/newEnv`;
      fetch(url, {
        body: JSON.stringify(postData),
        headers: {
          'Content-Type': 'application/json;charset=utf-8',
        },
        method: 'POST',
      })
        .then((response) => response.json())
        .then((res) => {
          const { code, msg } = res;
          if (code === 200) {
            ElMessage.success({
              message: msg || '新建环境成功',
              type: 'success',
            });
          } else {
            ElMessage.error(msg || '获取环境目录失败');
          }
        });
    } catch (error) {
      console.log(error);
      ElMessage.error('请求发生了错误，请稍后重试');
    } finally {
      loadTreeData();
    }
  });
};

const saveContent = (event: KeyboardEvent) => {
  if (event.ctrlKey && event.key === 's') {
    event.preventDefault();
    onCommand({ command: 'saveFile' });
  }
};

onMounted(() => {
  loadTreeData();
  document.addEventListener('keydown', saveContent);
});

onBeforeUnmount(() => {
  document.removeEventListener('keydown', saveContent);
  editorElRef.value?.dispose(editorValue.value);
});

watch(
  () => appStore.windowState,
  () => {
    setTimeout(() => {
      if (documentElRef.value) {
        documentHeight.value = documentElRef.value.offsetHeight;
      }
    }, 600);
  },
  { deep: true, immediate: true },
);

watch(
  () => modifiedContent.value,
  (newValue) => {
    contentChanged.value = newValue !== _modifiedContent.value;
  },
);
</script>

<template>
  <div ref="documentElRef" class="wos-release">
    <Horizontal :default-width="260" :max-width="480" :min-width="260" :now-rect="nowRect" @resize="onHorizontalResize">
      <template #aside>
        <div class="side-left">
          <div class="toolbar">
            <ElButtonGroup>
              <ElButton size="small" @click="setCheckedKeys"> 全选 </ElButton>
              <ElButton size="small" @click="setReverseChecked">
                反选
              </ElButton>
              <ElButton size="small" @click="resetChecked"> 清空 </ElButton>
              <ElButton size="small" title="新增环境" @click="addEnvironment">
                新增
              </ElButton>
              <ElButton size="small" @click="removeChecked"> 删除 </ElButton>
            </ElButtonGroup>
          </div>
          <div class="content">
            <ElTree ref="treeRef" :data="treeData" :highlight-current="true" :props="defaultProps"
              class="release-custom-tree" node-key="id" show-checkbox size="small" @node-click="handleNodeClick">
              <template #default="{ node, data }">
                <div :title="node.label" class="custom-tree-node">
                  <CheckboxVersion :item="data" :level="node.level" @compare="onCompare" @delete="onDelete" />
                </div>
              </template>
            </ElTree>
          </div>
        </div>
      </template>
      <template #main>
        <div class="content-right">
          <Toolbar :content-changed="contentChanged" :modified-option="modifiedOption" :original-option="originalOption"
            :readonly="readonly" :show-diff="showDiff" @on-command="onCommand" />
          <Suspense>
            <template #default>
              <component :is="showDiff ? CodeDiffEditor : CodeEditor" ref="editorElRef" v-model:value="modifiedContent"
                :height="documentHeight" :modified="modifiedContent" :name="editorValue" :original="originalContent"
                :toolbar-height="42" ext=".py" @editor-diff-dispose="onEditorDiffDispose" />
            </template>
            <template #fallback>
              <div class="flex items-center justify-center h-full pt-12">
                Loading CodeEditor...
              </div>
            </template>
          </Suspense>
        </div>
      </template>
    </Horizontal>
    <Teleport to="body">
      <SaveTo ref="saveToRef" @confirm="onReleaseToConfirm" />
    </Teleport>
    <Teleport to="body">
      <VersionDialog ref="versionDialogElRef" :list="treeData" @confirm="onMoveToConfirm" />
    </Teleport>
    <Teleport to="body">
      <!--更多设置-->
      <MonacoEditorSetting ref="moreSettingElRef" />
    </Teleport>
    <Teleport to="body">
      <SelectByFileType ref="selectByFileTypeRef" @confirm="onSelectConfirm" />
    </Teleport>
  </div>
</template>

<style lang="scss">
@import url('./css/release.scss');
</style>
